package com.ds.home.engine;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ds.command.Command;
import com.ds.command.InitGatewayCommand;
import com.ds.common.logging.Log;
import com.ds.common.logging.LogFactory;
import com.ds.common.query.Condition;
import com.ds.common.query.JLuceneIndex;
import com.ds.config.ListResultModel;
import com.ds.home.*;
import com.ds.home.database.MEMManagerImpl;
import com.ds.home.database.manager.EIDBManager;
import com.ds.home.query.HomeConditionKey;
import com.ds.home.query.IOTConditionKey;
import com.ds.iot.Device;
import com.ds.iot.HomeConstants;
import com.ds.iot.HomeException;
import com.ds.iot.Sensortype;
import com.ds.iot.enums.DeviceStatus;
import com.ds.iot.enums.ZNodeZType;
import com.ds.iot.json.device.Gateway;
import com.ds.iot.json.device.GatewayErrorReport;
import com.ds.jds.core.User;
import com.ds.org.Person;
import com.ds.org.PersonNotFoundException;
import com.ds.server.OrgManagerFactory;

import java.util.*;

public class GWEngine {
    private final Log log = LogFactory.getLog(HomeConstants.CONFIG_ENGINE_KEY, GWEngine.class);

    public static final String USERID = "GWEngine.USERID";

    public String systemCode;

    static EIDBManager manager;

    private static final Map<String, GWEngine> engineMap = new HashMap();

    private static final Map<String, String> systemIdieeeMap = new HashMap();

    protected static GWEngine getEngine(final String systemCode) {
        GWEngine engine = (GWEngine) engineMap.get(systemCode);
        if (engine == null) {
            synchronized (GWEngine.class) {
                engine = new GWEngine(systemCode);
                engineMap.put(systemCode, engine);
            }
        }
        return engine;
    }

    public static GWEngine getDefaultEngine() {
        final String systemCode = "org";
        GWEngine engine = (GWEngine) engineMap.get(systemCode);
        if (engine == null) {
            synchronized (GWEngine.class) {
                engine = new GWEngine(systemCode);
                engineMap.put(systemCode, engine);
            }
        }
        return engine;
    }

    public GWEngine(final String systemCode) {
        this.systemCode = systemCode;
        manager = MEMManagerImpl.getInstance();
    }


    public ListResultModel<Set<String>> findPlace(Condition<HomeConditionKey, JLuceneIndex> condition) {
        return manager.findPlace(condition);
    }

    ;

    public ListResultModel<Set<String>> findArea(Condition<HomeConditionKey, JLuceneIndex> condition) {
        return manager.findArea(condition);
    }

    ;

    public ListResultModel<Set<String>> findDevice(Condition<IOTConditionKey, JLuceneIndex> condition) {
        return manager.findDevice(condition);
    }

    ;

    public ListResultModel<Set<String>> findEndPoint(Condition<IOTConditionKey, JLuceneIndex> condition) {
        return manager.findEndPoint(condition);
    }

    ;

    public ListResultModel<Set<String>> findZNode(Condition<IOTConditionKey, JLuceneIndex> condition) {
        return manager.findZNode(condition);
    }

    ;

    public ListResultModel<Set<String>> findAlarm(Condition<HomeConditionKey, JLuceneIndex> condition) {
        return manager.findAlarm(condition);
    }

    ;

    public ListResultModel<Set<String>> findScene(Condition<HomeConditionKey, JLuceneIndex> condition) {
        return manager.findScene(condition);
    }

    ;


    public void removeChildDevice(final String bindingAccount, final String chileDeviceId) throws HomeException {

        final EIDevice parentDevice = getDeviceById(bindingAccount);
        parentDevice.removeChildDevice(chileDeviceId);

    }

    protected static String getSystemCodeByIeee(final String serialno) {
        final GWEngine engine = getDefaultEngine();
        String systemCode = "";
        try {
            final EIDevice device = engine.getDeviceBySerialno(serialno);
            if (device != null)
                systemCode = engine.getDeviceBySerialno(serialno).getSubsyscode();
        } catch (final HomeException e) {
            e.printStackTrace();
        }
        return systemCode;
    }

    public EIPlace bindingPlace(final String gwieee, final String placeId) throws HomeException {
        final EIDevice device = getDeviceByIeee(gwieee);
        device.setPlaceid(placeId);
        final EIPlace place = getPlaceById(placeId);
        updateDevice(device, true);
        return place;
    }


//
//    public EIArea bindingArea(final String sessionieee, final String areaid) throws HomeException {
//        final EIDevice device = getDeviceByIeee(sessionieee);
//        final EIArea area = getAreaById(areaid);
//        device.setAreaid(areaid);
//        device.setPlaceid(area.getPlaceid());
//        updateDevice(device, true);
//        return area;
//    }

    public EIDevice getDeviceByIeee(final String ieee) {
        final GWEngine engine = getDefaultEngine();
        EIDevice device = null;
        // 静态方法清除缓存预防集群不一致
        // CacheManagerFactory.getCache(systemCode, "serialnoCache").remove(ieee);
        try {
            device = engine.getDeviceBySerialno(ieee);
        } catch (final HomeException e) {
            e.printStackTrace();
        }
        return device;
    }

    public EIDevice getGWDeviceByIeee(final String sessionieee) throws HomeException {

        final String bindaccount = getDeviceByIeee(sessionieee).getBindingaccount();
        final EIDevice gwdevice = getDeviceById(bindaccount);
        return gwdevice;
    }

    public EIDevice getGWDeviceByZNodeId(final String znodeId) throws HomeException {

        final String bindaccount = getDeviceByNodeId(znodeId).getBindingaccount();
        final EIDevice gwdevice = getDeviceById(bindaccount);
        return gwdevice;
    }

    public List<String> getDeviceIdsByChannel(final String channel) throws HomeException {

        final List<String> deviceIds = new ArrayList<String>();

        final List<EIDevice> devices = manager.findDeviceByChannel(channel);

        for (final EIDevice device : devices) {
            deviceIds.add(device.getDeviceid());
        }
        return deviceIds;
    }

    public List<String> getDevicesIdsByArea(final String areaId) throws HomeException {
        final List<String> deviceIds = new ArrayList<String>();

        final List<EIDevice> devices = manager.findDeviceByArea(areaId);

        for (final EIDevice device : devices) {
            deviceIds.add(device.getDeviceid());
        }
        return deviceIds;

    }


    private String rePlaceName(String name, final List<EIPlace> places) {
        if (!name.endsWith(")")) {
            name = name + "(1)";
        }

        Integer index = Integer.valueOf(2);
        final String realName = name.substring(0, name.indexOf("("));
        for (final EIPlace dbPlace : places) {
            if (dbPlace.getName().startsWith(realName)) {
                index = Integer.valueOf(index.intValue() + 1);
            }
        }
        name = realName + "(" + index + ")";
        return name;
    }

    private String reAreaName(String name, final List<EIArea> areas) {
        if (!name.endsWith(")")) {
            name = name + "(1)";
        }
        Integer index = Integer.valueOf(2);
        final String realName = name.substring(0, name.indexOf("("));
        for (final EIArea dbArea : areas) {
            if (dbArea.getName().startsWith(realName)) {
                index = Integer.valueOf(index.intValue() + 1);
            }
        }
        name = realName + "(" + index + ")";
        return name;
    }


    public EIPlace createPlace(final String name, final String parentId, String userId) throws HomeException {
        final List<EIPlace> places = manager.findPlaceByName(name, parentId, userId);

        EIPlace place = null;
        if (places == null || places.isEmpty()) {

            place = manager.createPlace(name, parentId, userId);
        } else {
            place = places.get(0);
        }

        return place;
    }

    public EIArea getAreaById(final String areaId) throws HomeException {
        final EIArea area = manager.getAreaById(areaId);

        if (area == null) {
            throw new HomeException("areaid [" + areaId + "] is not exits!", HomeException.AREANOTEXITS);
        }
        return area;
    }

    public boolean checkAreaName(final String name, final String placeId) throws HomeException {
        if ((name == null) || (name.equals(""))) {
            throw new HomeException("房间名称不能为空", 8002);
        }
        final EIPlace place = getPlaceById(placeId);

        final List<EIArea> areas = place.getAreas();

        for (final EIArea dbarea : areas) {
            if (dbarea.getName().equals(name)) {
                return true;
            }
        }
        return false;
    }

    public EIArea createArea(final String name, final String placeId) throws HomeException {
        if (checkAreaName(name, placeId)) {
            throw new HomeException("房间名称已存在", 8002);
        }

        EIPlace place = manager.getPlaceById(placeId);

        final EIArea area = manager.createArea(name, placeId);

        place.addArea(area);


        return area;
    }

    /**
     * 物理删除数据
     *
     * @param deviceId
     * @throws HomeException
     */
    public void deleteGateway(final String deviceId) throws HomeException {
        final EIDevice device = getDeviceById(deviceId);
        final List<Device> devices = new ArrayList<Device>();
        final Set<String> deviceIds = device.getChildDeviceIds();
        for (final String childdeviceId : deviceIds) {
            this.deleteDevice(childdeviceId);
            manager.deleteDevice(childdeviceId);
        }
        this.deleteDevice(deviceId);
        manager.deleteDevice(deviceId);

    }

    /**
     * 逻辑删除
     *
     * @param deviceId
     * @throws HomeException
     */
    public void deleteDevice(final String deviceId) throws HomeException {
        final EIDevice dbDevice = getDeviceById(deviceId);
        final List<EIZNode> znodes = getAllZNodeByDeviceId(deviceId);

        for (final EIZNode znode : znodes) {
            if (znode.getZtype().equals(ZNodeZType.SHARE.getType())) {
                try {
                    deleteNode(znode.getZnodeid());
                } catch (final HomeException e) {
                    e.printStackTrace();
                }
            } else {
                znode.setStatus(DeviceStatus.DELETE.getCode());
            }
        }
        dbDevice.setAppaccount(dbDevice.getBindingaccount());
    }

    public void deleteArea(final String areaId) throws HomeException {
        manager.deleteAreaById(areaId);
    }

    public void deletePlace(final String placeId) throws HomeException {
        manager.deletePlaceById(placeId);
    }

    public EIDevice getDeviceById(final String deviceId) throws HomeException {
        final EIDevice device = manager.getDeviceById(deviceId);
        if (device == null) {
            throw new HomeException("deviceId :[" + deviceId + "] not exits!", HomeException.DEVICENOEXITS);
        }
        return device;
    }

    public EIDevice getDeviceByNodeId(final String nodeId) throws HomeException {
        final EIZNode node = getZNodeById(nodeId);
        final EIDevice device = manager.getDeviceById(node.getDeviceid());
        return device;
    }

    public EIDevice getDeviceBySerialno(String serialno) throws HomeException {


        EIDevice device = manager.getDeviceBySerialno(serialno);

        if (device == null) {
            device = manager.getDeviceByMacaddress(serialno);
        }

        if (device == null) {
            throw new HomeException("getDeviceBySerialno serialno[" + serialno + "] is not exits!", HomeException.DEVICENOEXITS);
        }

        return device;
    }

    public List<EIDevice> getDeviceByBindAccount(final String account) throws HomeException {
        final List<EIDevice> devices = manager.getDevicesByBindAccount(account);

        return devices;
    }

    public List<String> getDeviceIdsByBindAccount(final String account) throws HomeException {
        final List<String> deviceIds = new ArrayList<String>();
        final List<EIDevice> devices = manager.getDevicesByBindAccount(account);
        for (final EIDevice device : devices) {
            deviceIds.add(device.getDeviceid());
        }

        return deviceIds;
    }

    public EIZNode findZNodeByEndPointId(final String endPointId, final String personId) throws HomeException {
        final EIDeviceEndPoint endPoint = getEndPonitById(endPointId);
        final List<EIZNode> znodes = endPoint.getAllZNodes();
        for (final EIZNode znode : znodes) {
            if (znode.getCreateuiserid().equals(personId)) {
                return znode;
            }
        }
        throw new HomeException("endPointId :[" + endPointId + "] in user: [" + personId + "] not exits!");

    }

    public void updateDevice(final EIDevice device) throws HomeException {
        manager.updateDevice(device, true);
    }

    public void updateDevice(final EIDevice device, final boolean indb) throws HomeException {
        manager.updateDevice(device, indb);
    }

    public void updateEndPoint(final EIDeviceEndPoint endPoint) throws HomeException {
        manager.updateEndPoint(endPoint);
    }

    public void updateEndPoint(final EIDeviceEndPoint endPoint, final boolean indb) throws HomeException {
        manager.updateEndPoint(endPoint, indb);
    }

    public void updateZNode(final EIZNode node, final boolean indb) throws HomeException {
        manager.updateZNode(node, indb);
    }
    // public void updateZNode(EIZNode node) throws HomeException {
    // manager.updateZNode(node);
    // }

    public EIZNode createChildZNode(final String parentNodeId, final String endpointid) throws HomeException {
        return manager.createChildZNode(parentNodeId, endpointid);
    }

    public EIZNode createRootZNode(final String endpointid, final String placeId, final String createuiserid) throws HomeException {
        final EIDeviceEndPoint endPoint = getEndPonitById(endpointid);
        if (placeId == null) {
            throw new HomeException("placeId is null ", HomeException.PLACENOTEXITS);
        }
        return manager.createRootZNode(endpointid, placeId, createuiserid, ZNodeZType.GATEWAY);
    }

    public EIZNode createRootZNode(final String endpointid, final String placeId, final String createuiserid, ZNodeZType type) throws HomeException {
        final EIDeviceEndPoint endPoint = getEndPonitById(endpointid);
        if (placeId == null) {
            throw new HomeException("placeId is null ", HomeException.PLACENOTEXITS);
        }
        return manager.createRootZNode(endpointid, placeId, createuiserid, type);
    }

    public void updateNodeStatus(final String znodeId, final DeviceStatus status) throws HomeException {

        getZNodeById(znodeId).setStatus(status.getCode());
    }

    public void deleteNode(final String nodeId) throws HomeException {
        final EIZNode znode = getZNodeById(nodeId);

        if (znode.getEndPoint() != null) {
            znode.getEndPoint().removeZNode(nodeId);
        }

        if (znode.getParentNode() != null) {
            znode.getParentNode().removeZNode(nodeId);
        }

        manager.deleteZNodeById(nodeId);
    }

    public EIDeviceEndPoint registerEndPoint(final String sensorieee, final String epieee, final String ep, final Integer sensorType, final String name) throws HomeException

    {
        final EIDevice dbDevice = getDeviceByIeee(sensorieee);
        EIDeviceEndPoint dbep = manager.getEPBySerialno(epieee);
        if (dbep == null) {
            dbep = manager.createEndPoint(dbDevice.getDeviceid(), epieee, ep, sensorType, name);
        }
        dbDevice.addEndPoint(dbep);
        if (!dbDevice.isRoot()) {
            final List<EIZNode> gwznodes = dbDevice.getRootDevice().getDeviceEndPoints().get(0).getAllZNodes();
            for (final EIZNode gwznode : gwznodes) {
                createChildZNode(gwznode.getZnodeid(), dbep.getEndPointId());
            }

        }

        return dbep;
    }

    public EIDeviceEndPoint getEndPointByIeee(final String epieee) throws HomeException {
        final EIDeviceEndPoint dbep = manager.getEPBySerialno(epieee);
        return dbep;
    }

    public EIDevice createRootDevice(final String deviceId, final String serialno, final String macaddress, final String factory, final String version) throws HomeException {
        return manager.createRootDevice(deviceId, serialno, macaddress, factory, version);
    }

    public EIDevice createDevice(final String serialno, final String macaddress, final Integer type, final String factory, final String bindingAccount) throws HomeException {
        return manager.createDevice(serialno, macaddress, type, factory, bindingAccount);
    }

    //
    // public EIDevice registerDevice(String serialno, String gwDeviceId,
    // Integer deviceType, String account, String factoryName) throws
    // HomeException
    //
    //
    //
    // {
    // EIDevice sensorDevice = null;
    //
    // EIDevice gwDevice = this.getDeviceById(gwDeviceId);
    //
    // try {
    // sensorDevice = getDeviceBySerialno(serialno);
    // sensorDevice.setSerialno(serialno);
    // sensorDevice.setBindingaccount(gwDeviceId);
    // sensorDevice.setAppaccount(account);
    // EISensortype sensortype = null;
    // try {
    // sensortype = getSceneByNo(deviceType);
    // } catch (HomeException e) {
    // e.printStackTrace();
    // }
    // if (sensortype != null) {
    // sensorDevice.setDevicetype(sensortype.getType());
    // sensorDevice.setName(sensortype.getName());
    // }
    // sensorDevice.setBindingaccount(gwDeviceId);
    //
    // if (factoryName == null) {
    // sensorDevice.setFactory(gwDevice.getFactory());
    // }
    //
    // sensorDevice.setSubsyscode(gwDevice.getSubsyscode());
    // sensorDevice.setStates(HomeConstants.DEVICE_STATUS_ONLINE);
    // this.manager.updateDevice(sensorDevice);
    // } catch (HomeException e) {
    //
    // }
    // if (sensorDevice == null) {
    // sensorDevice = new EIDevice();
    // sensorDevice.setDeviceid(UUID.randomUUID().toString());
    //
    // sensorDevice.setSerialno(serialno);
    // sensorDevice.setBindingaccount(gwDeviceId);
    // sensorDevice.setAppaccount(account);
    //
    // EISensortype sensortype = null;
    // try {
    // sensortype = getSceneByNo(deviceType);
    // } catch (HomeException e) {
    // e.printStackTrace();
    // }
    // if (sensortype != null) {
    // sensorDevice.setDevicetype(sensortype.getType());
    // sensorDevice.setName(sensortype.getName());
    // }
    // sensorDevice.setBindingaccount(gwDeviceId);
    //
    // if (factoryName == null) {
    // sensorDevice.setFactory(gwDevice.getFactory());
    // }
    //
    // sensorDevice.setSubsyscode(gwDevice.getSubsyscode());
    // sensorDevice.setStates(HomeConstants.DEVICE_STATUS_ONLINE);
    // this.manager.createDevice(sensorDevice);
    // }
    //
    //
    // return sensorDevice;
    // }

    public EIZNode copyGateway(final String sourceNodeId, final String personId, final ZNodeZType type, String placeId) throws HomeException {
        final EIZNode sourceNode = getZNodeById(sourceNodeId);
        final EIPlace dbsplace = getPlaceById(sourceNode.getEndPoint().getDevice().getRootDevice().getPlaceid());
        EIPlace copyPlace = null;
        if (placeId != null) {
            copyPlace = getPlaceById(placeId);
        } else {
            copyPlace = manager.createPlace(dbsplace.getName() + "（共享）", "root", personId);
            copyPlace.setPlaceid(UUID.randomUUID().toString());
            copyPlace.setName(dbsplace.getName() + "（共享）");
            placeId = copyPlace.getPlaceid();
            copyPlace.setMemo(dbsplace.getMemo());
            copyPlace.setStart(dbsplace.getMemo());
            copyPlace.setUserid(personId);
            updatePlace(copyPlace);
        }

        final EIDeviceEndPoint endPoint = getEndPonitById(sourceNode.getEndPointid());

        final EIZNode copyPnode = manager.createRootZNode(endPoint.getEndPointId(), copyPlace.getPlaceid(), personId, ZNodeZType.SHARE);

        final List<EIZNode> sourceSensors = manager.getAllChildZNode(sourceNode.getZnodeid());

        for (final EIZNode cnode : sourceSensors) {

            final EIZNode copyCnode = manager.createChildZNode(endPoint.getEndPointId(), endPoint.getEndPointId());

            final List<EIAlarm> alarms = getAlarmBySensorId(cnode.getZnodeid());
            for (final EIAlarm alarm : alarms) {
                final EIAlarm copyAlarm = alarm.clone(cnode.getZnodeid());
                updateAlarm(copyAlarm);
            }
        }

        return copyPnode;
    }

    public EIZNode getZNodeById(final String nodeId) throws HomeException {
        final EIZNode node = manager.getZNodeById(nodeId);

        if (node == null) {

            throw new HomeException("SensorId not exits!", HomeException.SENSORIDINVALID);
        }
        return node;
    }

    public EIPlace getPlaceById(final String placeId) throws HomeException {
        final EIPlace place = manager.getPlaceById(placeId);
        if (place == null) {
            throw new HomeException("place not exits!", HomeException.PLACENOTEXITS);
        }

        return place;
    }

    private Person getEIPerson(final String personId) throws HomeException {
        Person person = null;
        try {
            person = OrgManagerFactory.getOrgManager().getPersonByID(personId);
        } catch (final PersonNotFoundException e) {
            throw new HomeException("用户不存在", 1003);
        }
        return person;
    }

    public void setSystemCode(final String code) {
        systemCode = code;
    }

    public String getSystemCode() {
        return systemCode;
    }

    public List<EIArea> getAreasByPalceId(final String placeId) throws HomeException {

        final EIPlace place = getPlaceById(placeId);

        return place.getAreas();
    }

    public Set<String> getAreaIdsByPalceId(final String placeId) throws HomeException {
        final EIPlace place = getPlaceById(placeId);
        return place.getAreaIds();
    }

    public List<EIPlace> getAllPlace(final String personId) throws HomeException {
        return manager.findPlaceByPersonId(personId);
    }

    public List<String> getAllPlacesIdByUserId(final String personId) throws HomeException {
        final List<String> placeIds = new ArrayList<String>();
        final List<EIPlace> placeInfos = manager.findPlaceByPersonId(personId);
        for (final EIPlace place : placeInfos) {
            placeIds.add(place.getPlaceid());
        }
        return placeIds;
    }

    public List<String> getAllPlacesIdByOrgId(final String orgId) throws HomeException {
        final List<String> placeIds = new ArrayList<String>();
        final List<EIPlace> placeInfos = manager.findPlaceByOrgId(orgId);
        for (final EIPlace place : placeInfos) {
            placeIds.add(place.getPlaceid());
        }
        return placeIds;
    }

    public List<String> findAllOrgPlaceIds() throws HomeException {
        final List<String> placeIds = new ArrayList<String>();
        final List<EIPlace> placeInfos = manager.findAllOrgPlace();
        for (final EIPlace place : placeInfos) {

            placeIds.add(place.getPlaceid());
        }
        return placeIds;
    }

    public List<String> findAllChildPlaceIds(final String placeId) {
        final List<String> placeIds = new ArrayList<String>();
        final List<EIPlace> placeInfos = manager.getChildPlaces(placeId);
        for (final EIPlace place : placeInfos) {
            if (place != null) {
                placeIds.add(place.getPlaceid());
            }

        }
        return placeIds;
    }

    public List<String> findAllPersonPlaceIds() throws HomeException {
        final List<String> placeIds = new ArrayList<String>();
        final List<EIPlace> placeInfos = manager.findAllPersonPlace();
        for (final EIPlace place : placeInfos) {
            placeIds.add(place.getPlaceid());
        }
        return placeIds;
    }

    public List<EIZNode> getAllZChildNode(final String parentNodeId) throws HomeException {
        final List childNode = manager.getAllChildZNode(parentNodeId);
        return childNode;
    }


    public List<String> getAllChildNodeIds(final String parentNodeId) throws HomeException {
        final EIZNode znode = getZNodeById(parentNodeId);
        return znode.getAllZNodeIds();
    }

    public List<EIDevice> getAllChildDevice(final String parentNodeId) throws HomeException {
        final List<EIDevice> devices = new ArrayList<EIDevice>();
        final List<EIZNode> childNodes = manager.getAllChildZNode(parentNodeId);

        for (final EIZNode dbznode : childNodes) {
            final EIDevice device = getDeviceById(dbznode.getDeviceid());
            devices.add(device);
        }
        return devices;
    }

    public List<EIDevice> getDevicesByPlaceId(final String placeId) throws HomeException {
        final List<EIDevice> devices = manager.findDeviceByPlace(placeId);

        return manager.findDeviceByPlace(placeId);
    }

    public List<String> getGWDevicesByPlaceId(final String placeId) throws HomeException {
        final List<String> devices = new ArrayList<String>();

        for (EIDevice device : manager.findDeviceByPlace(placeId)) {
            if (device.getDevicetype().equals(0)) {
                devices.add(device.getDeviceid());
            }
        }


        return devices;
    }


    public Set<String> getAllChildDeviceIds(final String parentNodeId) throws HomeException {

        final EIDevice device = getZNodeById(parentNodeId).getEndPoint().getDevice().getRootDevice();

        final Set<String> deviceIds = device.getChildDeviceIds();

        return deviceIds;
    }

    public List<EIZNode> getAllShareChildNode(final String parentNodeId) throws HomeException {
        final List shareChildNode = new ArrayList();
        final List<EIZNode> childNodes = manager.getAllChildZNode(parentNodeId);
        for (final EIZNode dbznode : childNodes) {
            final List shareNodes = getAllZNodeByDeviceId(dbznode.getDeviceid());
            shareChildNode.addAll(shareNodes);
        }
        return shareChildNode;
    }

    public List<EIZNode> getChildNodeById(final String nodeId) throws HomeException {
        final List childNode = manager.getAllChildZNode(nodeId);
        return childNode;
    }

    public void updateArea(EIArea area) throws HomeException {

        manager.updateArea(area);
    }


    public void updateAreaName(final String areaId, String name) throws HomeException {
        if ((name == null) || (name.equals(""))) {
            throw new HomeException("房间名称不能为空", 8002);
        }
        final EIArea area = manager.getAreaById(areaId);
        final List<EIArea> areas = manager.getAreasByPlaceId(area.getPlaceid());
        boolean nameIsExits = false;

        for (final EIArea dbarea : areas) {
            if (dbarea.getName().equals(name)) {
                nameIsExits = true;
                throw new HomeException("房间名称已存在", 8002);
            }
        }
        if (nameIsExits) {
            name = reAreaName(name, areas);
        }

        area.setName(name);
        manager.updateArea(area);
    }

    public void updatePlace(final EIPlace place) throws HomeException {
        manager.updatePlace(place);
    }

    public EIAlarm getAlarmById(final String alarmId) throws HomeException {

        final EIAlarm alarm = manager.getAlarmById(alarmId);
        if (alarm == null) {
            throw new HomeException("指定警告信息不存在！", HomeException.ALARMNOTEXITS);
        }

        return alarm;
    }

    public void updateAlarm(final EIAlarm alarm) throws HomeException {
        manager.updateAlarm(alarm);
    }

    public void deleteAlarm(final String alarmid) throws HomeException {
        manager.deleteAlarmById(alarmid);
    }

    public List<EIArea> getAreasByPersonId(final String personId) throws HomeException {
        return manager.getAreasByPersonId(personId);
    }


//
//    public List<String> getAllZNodeIdsByAreaId(final String deviceid) throws HomeException {
//
//        final List<String> znodeIds = new ArrayList<String>();
//        final List<EIZNode> znodeInfos = manager.getZNodesByAreaId(deviceid);
//        for (final EIZNode dbznode : znodeInfos) {
//            znodeIds.add(dbznode.getZnodeid());
//        }
//        return znodeIds;
//    }

//
//    public List<EIZNode> getZNodeByAreaId(final String areaId) throws HomeException {
//        return manager.getZNodesByAreaId(areaId);
//    }
//

    public EISensortype getSensoTypeById(final String sensortypeId) throws HomeException {
        return manager.getSensoTypeById(sensortypeId);
    }

    public void updateScene(final EIScene scene) throws HomeException {
        manager.updateScene(scene);
    }

    public void deleteScene(final String sceneId) throws HomeException {
        manager.deleteScene(sceneId);
    }

    public EIScene getSceneById(final String sceneId) throws HomeException {
        return manager.getSceneById(sceneId);
    }

    public List<EIScene> getSceneBySensorId(final String sensorId) throws HomeException {
        final List scenes = manager.getScenesBySensorId(sensorId);
        return scenes;
    }

    public List<String> getSceneIdsBySensorId(final String sensorId) throws HomeException {

        final List<String> sceneIds = new ArrayList<String>();
        final List<EIScene> sceneInfos = manager.getScenesBySensorId(sensorId);
        for (final EIScene dbscene : sceneInfos) {
            sceneIds.add(dbscene.getSceneid());
        }
        return sceneIds;
    }

    public EISensortype getSensortypeByNo(final Integer no) throws HomeException {
        final EISensortype type = manager.getSensoTypeByNo(no);

        return type;
    }

    public void addAlarm(final List<EIAlarm> alarms) throws HomeException {
        for (final EIAlarm alarm : alarms) {
            manager.updateAlarm(alarm);
        }
    }

    public List<User> getAllUserByDeviceId(final String deviceid) throws HomeException {
        final List<EIZNode> nodes = manager.getZNodesByDeviceId(deviceid);
        final List users = new ArrayList();

        for (final EIZNode node : nodes) {
            if ((node.getZtype().equals(ZNodeZType.SHARE)) && (!node.getStatus().equals(DeviceStatus.DELETE.getCode()))) {
                users.add(getUserById(node.getCreateuiserid()));
            }
        }

        return users;
    }

    public List<EIZNode> getAllZNodeByDeviceId(final String deviceid) throws HomeException {
        final List<EIZNode> nodes = manager.getZNodesByDeviceId(deviceid);

        return nodes;
    }

    public List<EIZNode> getAllZNodeByEndPointId(final String endPointId) throws HomeException {

        final List<EIZNode> znodes = new ArrayList<EIZNode>();
        final List<String> znodeids = getAllZNodeIdsByEndPointId(endPointId);
        for (final String nodeId : znodeids) {

            final EIZNode znode = getZNodeById(nodeId);
            if (znode != null) {
                znodes.add(znode);
            }

        }
        return znodes;
    }

    public List<String> getAllZNodeIdsByEndPointId(final String endPointId) throws HomeException {

        String idsjson = manager.getAllZNodeIdCache().get(endPointId);
        List<String> znodeIds = new ArrayList<String>();
        if (idsjson == null) {
            final List<EIZNode> znodes = manager.getZNodesByEndPointId(endPointId);
            for (final EIZNode znode : znodes) {
                znodeIds.add(znode.getZnodeid());
            }
            idsjson = JSONObject.toJSONString(znodeIds);
            manager.getAllEPIdCache().put(endPointId, JSONObject.toJSONString(znodeIds));
        }
        znodeIds = JSONArray.parseArray(idsjson, String.class);
        return znodeIds;
    }

    public List<String> getAllZNodeIdsByDeviceId(final String deviceid) throws HomeException {

        final List<String> znodeIds = new ArrayList<String>();
        final List<EIZNode> znodeInfos = manager.getZNodesByDeviceId(deviceid);
        for (final EIZNode dbznode : znodeInfos) {
            znodeIds.add(dbznode.getZnodeid());
        }
        return znodeIds;
    }

    public User getMainUserByDeviceId(final String serialno) throws HomeException {
        final EIDevice device = getDeviceBySerialno(serialno);
        return getUserByAccount(device.getAppaccount());
    }

    private User getUserByAccount(final String personAccount) throws HomeException {

        Person person = null;
        try {
            person = OrgManagerFactory.getOrgManager().getPersonByAccount(personAccount);
        } catch (final PersonNotFoundException e) {
            throw new HomeException("账户不存在", 1003);
        }
        final User user = new User();
        user.setAccount(person.getAccount());
        user.setId(person.getID());
        user.setEmail(person.getEmail());
        user.setPhone(person.getMobile());
        user.setName(person.getName());
        return user;
    }

    private User getUserById(final String Id) throws HomeException {

        Person person = null;
        try {
            person = OrgManagerFactory.getOrgManager().getPersonByID(Id);
        } catch (final PersonNotFoundException e) {
            throw new HomeException("账户不存在", 1003);
        }
        final User user = new User();
        user.setAccount(person.getAccount());
        user.setId(person.getID());
        user.setEmail(person.getEmail());
        user.setPhone(person.getMobile());
        user.setName(person.getName());
        return user;
    }

    public List<EIAlarm> getAlarmBySensorId(final String sensorId) throws HomeException {
        final List alarmList = manager.getAlarmsBySensorId(sensorId);
        return alarmList;
    }

    public List<String> getAlarmIdsBySensorId(final String sensorId) throws HomeException {
        final List<String> alarmIds = new ArrayList<String>();
        final List<EIAlarm> alarmInfos = manager.getAlarmsBySensorId(sensorId);
        for (final EIAlarm dbaream : alarmInfos) {
            alarmIds.add(dbaream.getAlarmid());
        }
        return alarmIds;
    }

    //
    // public List<EIZNode> getZNodeByCreateId(String userId) {
    // return manager.getAllZNodeByCreateId(userId);
    // }
    // public List<EIZNode> getZNodeByCreateId(String userId,Integer type) {
    // return this.manager.getNodeByCreateId(userId,type);
    // }
    //
    //
    // public EIZNode getMainZNodeByDeviceId(String deviceId) {
    // EIZNode dbznonde =manager.getMainZNodeByDeviceId(deviceId);
    //
    // return dbznonde;
    // }
    //
    // public List<String> getZNodeIdsByCreateId(String userId) {
    //
    // List<String> znodeIds = new ArrayList<String>();
    // List<EIZNode> znodeInfos = this.manager.getNodeByCreateId(userId);
    // for (EIZNode dbznode : znodeInfos) {
    // znodeIds.add(dbznode.getZnodeid());
    // }
    // return znodeIds;
    //
    // }

    public EIAlarm creatAlarm(final String sensorId) throws HomeException {
        final EIAlarm dbAlarm = manager.creatAlarm(sensorId);
        return dbAlarm;
    }

    public EIScene creatScene(final String sensorId) throws HomeException {
        return manager.creatScene(sensorId);
    }

    public EIDeviceEndPoint getEndPointBySerialno(String serialno) throws HomeException {

        final EIDeviceEndPoint ep = manager.getEPBySerialno(serialno);

        if (ep == null) {
            throw new HomeException("serialno[" + serialno + "] is not exits!", HomeException.DEVICENOEXITS);
        }

        return ep;
    }

    public List<EIDeviceEndPoint> getAllEndPoints(final String deviceId) throws HomeException {
        final List<EIDeviceEndPoint> enpoinds = new ArrayList<EIDeviceEndPoint>();
        final List<String> enpoindIds = getAllEndPointIds(deviceId);
        for (final String epId : enpoindIds) {

            final EIDeviceEndPoint endPoint = manager.getEndPoindById(epId);
            if (endPoint != null) {
                enpoinds.add(endPoint);
            }

        }
        return enpoinds;

    }

    public List<String> getAllEndPointIds(final String deviceId) throws HomeException {
        String idsjson = manager.getAllEPIdCache().get(deviceId);
        List enpoindIds = new ArrayList<String>();
        if (idsjson == null) {
            final List<EIDeviceEndPoint> eps = manager.getEndPointsByDeviceId(deviceId);
            for (final EIDeviceEndPoint ep : eps) {
                enpoindIds.add(ep.getEndPointId());
            }
            idsjson = JSONObject.toJSONString(enpoindIds);
            manager.getAllEPIdCache().put(deviceId, JSONObject.toJSONString(enpoindIds));
        }
        enpoindIds = JSONArray.parseArray(idsjson, String.class);
        return enpoindIds;
    }

    public EIDeviceEndPoint getEndPonitById(final String endPointId) throws HomeException {
        final EIDeviceEndPoint ep = manager.getEndPoindById(endPointId);

        if (ep == null) {
            throw new HomeException("endPointId[" + endPointId + "] is not exits!", HomeException.DEVICENOEXITS);
        }

        return ep;
    }

    public List<Command> gatewayErrorReport(final GatewayErrorReport errorPort) throws HomeException {
        final List<Command> commandList = new ArrayList<Command>();
        final InitGatewayCommand command = new InitGatewayCommand();
        command.setCommandId(UUID.randomUUID().toString());

        commandList.add(command);

        String serialno = errorPort.getSerialno();

        if (serialno != null) {
            if (serialno.trim().length() > 16) {
                serialno = serialno.trim().substring(0, 16);
            }

            final EIDevice device = getDeviceBySerialno(serialno);
            errorPort.getSerialno();
            // 版本号
            device.setBatch(errorPort.getCurrVersion());
            this.updateDevice(device);
        }
        return commandList;

    }

    public EIDeviceEndPoint activateGateway(final Gateway gateway) throws HomeException {
        log.error(JSONObject.toJSONString(gateway).toString());

        if (gateway.getSerialno() != null && !gateway.getSerialno().equals("")) {

        }

        final EIDevice device = manager.createRootDevice(gateway.getDeviceId(), gateway.getSerialno(), gateway.getMacno(), gateway.getFactory(), gateway.getVersion());

        EIDeviceEndPoint endPoint = null;

        if (device.getDeviceEndPoints().isEmpty()) {
            final String deviceName = getSensortypeByNo(0).getName();
            endPoint = registerEndPoint(device.getSerialno(), device.getSerialno(), null, 0, deviceName);

        } else {
            endPoint = device.getDeviceEndPoints().get(0);
        }

        if (device == null) {
            throw new HomeException("GatewayId 不存在，请先完成注册！ ", HomeException.USERNAMEONTEXITS);
        }

        final String accountname = device.getAppaccount();

        if (accountname == null) {
            throw new HomeException("网关未完成用户绑定 ", HomeException.USERNAMEONTEXITS);
        }

        String sysCode = device.getSubsyscode();
        if (sysCode == null) {
            sysCode = device.getFactory();
            device.setSubsyscode(sysCode);
        }

        return endPoint;

    }

    public EIDeviceEndPoint registerGateway(final String deviceid, final String serialno, final String macaddress, final String factoryName, final String version) throws HomeException {

        final EIDevice device = manager.createRootDevice(deviceid, serialno, macaddress, factoryName, version);

        EIDeviceEndPoint endpoint = null;
        if (device.getDeviceEndPoints().isEmpty()) {

            try {
                endpoint = registerEndPoint(serialno, device.getSerialno(), null, 0, device.getName());
            } catch (final HomeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        } else {
            endpoint = device.getDeviceEndPoints().get(0);
        }

        return endpoint;
    }

    public List<EIZNode> findZNodesByCreateId(final String userId) {
        final List<EIZNode> znodes = manager.findZNodesByCreateId(userId);

        return znodes;

    }

    public Set<Integer> getSensoTypesByBatch() throws HomeException {
        return getSensoTypesByBatch("default");

    }

    public Set<Integer> getSensoTypesByBatch(final String batch) throws HomeException {
        final Set<Integer> typeIds = new LinkedHashSet<>();
        final List<EISensortype> sensorTypeInfos = manager.getSensorTypeByDeivceId(batch);
        for (final EISensortype sensortype : sensorTypeInfos) {
            typeIds.add(sensortype.getType());
        }
        return typeIds;
    }

    public Set<String> findGWDevicesByFactory(String factoryName) {

        Set<String> deviceIds = manager.findGWDevicesByFactory(factoryName);

        return deviceIds;
    }

    public void updateSensorType(Sensortype sensortype) throws HomeException {
        EISensortype vo = null;
        if (sensortype.getTypeid() != null && !sensortype.getTypeid().equals("")) {
            vo = manager.getSensoTypeById(sensortype.getTypeid());
        } else {
            if (sensortype.getType() == null || this.getSensortypeByNo(sensortype.getType()) != null) {
                throw new HomeException("sensortype is null or " + sensortype.getType() + " is exits!");
            }
            vo = manager.createSensorType();
        }
        vo.setAlarmurl(sensortype.getAlarmurl());
        vo.setColor(sensortype.getColor());
        vo.setDatalisturl(sensortype.getDatalisturl());
        vo.setHtmltemp(sensortype.getHtmltemp());
        vo.setHisdataurl(sensortype.getHisdataurl());
        vo.setDeviceid(sensortype.getDeviceid());
        vo.setIcon(sensortype.getIcon());
        vo.setIcontemp(sensortype.getIcontemp());
        vo.setType(sensortype.getType());
        vo.setName(sensortype.getName());
        manager.updateSensorType(vo);

    }

    public void deleteSensorType(Integer typeno) throws HomeException {
        manager.deleteSensorType(typeno);
    }
}